/**
 * @name metrics
 * @author Sowmya Balasubramanian, Aaron Hong, David Robertson
 */

function MetricParams() {
    this.metricsData = undefined;
    this.playbackData = new Array(2);
    this.seqId = 0;
    this.currentData = 0;
    this.nextData = 0;
    this.waitForData = false;
    this.utilizationType = "percent";
    this.resolution = 240;
    this.aggrSeconds = 30;
    this.initialTimeoutInterval = 7500;
    // 15 seconds
    this.timeoutInterval = 15000;
    this.startSeconds = 0;
    this.endSeconds = 0;
    this.currentSeconds = 0;
    this.currentEndSeconds = 0;
    this.playbackOn = false;
    this.paused = false;
    this.index = 0;
}

function updateLinks() {
    if (!wm.metrics.metricsData) {
        return;
    }
    if (!wm.metrics.playbackOn) {
        updateInfoCard();
    } else {
        setTimeout(updateInfoCard, 400);
    }
    var udata = wm.metrics.metricsData;
    for (var x in udata) {
        updateLinksOnMap(x+"_in",udata[x]["in"].capacity,udata[x]["in"].utilization);
        // inbound and outbound capacity are the same
        updateLinksOnMap(x+"_out",udata[x]["in"].capacity,udata[x]["out"].utilization);
    }
}

function findEndSeconds() {
    wm.metrics.currentEndSeconds =
        wm.metrics.currentSeconds + wm.metrics.resolution*24;
    var timeRemaining = wm.metrics.endSeconds - wm.metrics.currentSeconds;
    if (timeRemaining < wm.metrics.resolution*24) {
        wm.metrics.currentEndSeconds = wm.metrics.currentSeconds +
                                       timeRemaining;
    }
}

function getMetrics() {
    if (wm.metrics.playbackOn) {
        return;
    }
    startWaitState();
    wm.metrics.seqId++;
    var metricReqParams = "";
    if (wm.weathermap.metricChoice == 1) {
        // The actual parameter doesn't matter, because we are just looking for whether it exists
        // TODO consider changing, generalizing this parameter a bit
        metricReqParams += "&metricsRequest={'reservations':'hi',";
    } else if (wm.weathermap.metricChoice == 2) {
        metricReqParams += "&metricsRequest={'mbps':'hi',";
    } else {
        metricReqParams += "&metricsRequest={";
    }
    // ignored on server if Percent Utilized chosen
    console.log("metricChoice: " + wm.weathermap.metricChoice);
    console.log("metricTypeChoice: " + wm.weathermap.metricTypeChoice);
    if (wm.weathermap.metricTypeChoice === 0) {
        metricReqParams += "'metricType':'average',";
    } else {
        metricReqParams += "'metricType':'max',";
    }
    console.log("aggrSeconds: " + wm.metrics.aggrSeconds);
    metricReqParams += "'aggrSeconds':'" + wm.metrics.aggrSeconds +
                       "','seqId':'" + wm.metrics.seqId + "'}";
    GDownloadUrl(servletUrl + "servlet/?", function(data) {
          updateMetrics(data);
    },"action=getMetrics"+metricReqParams);
}

function updateMetrics(data){
    stopWaitState();
    if (wm.metrics.playbackOn) {
        return;
    }
    if (checkError(data)) {
        return;
    }
    var parsedData;
    if (typeof(JSON) === 'object' &&
        typeof(JSON.parse) === 'function') {
        parsedData = JSON.parse(data); // native parsing available
    } else {
        parsedData = eval("(" + data + ")");
    }
    var seqIdRet = parsedData.seqId;
    // only want latest one
    if (wm.metrics.seqId > seqIdRet) {
        console.log("ignoring data");
        return;
    }
    setTimeout(getMetrics, wm.metrics.timeoutInterval);
    wm.metrics.metricsData = parsedData.utilizationData;
    wm.metrics.utilizationType = parsedData.utilizationType;
    GEvent.trigger(wm.weathermap.eventDummy, "metricsChanged");
}

function runLoop() {
    if (!wm.metrics.playbackOn) {
        return;
    }
    if (!wm.metrics.playbackData[wm.metrics.currentData].timelineData[wm.metrics.index]) {
        // if not waiting for the next download
        if (!wm.metrics.waitForData) {
            if (wm.metrics.currentEndSeconds == wm.metrics.endSeconds) {
                // start all over at the beginning
                wm.metrics.currentSeconds = wm.metrics.startSeconds;
            } else {
                // go to next group of time steps
                wm.metrics.currentSeconds += wm.metrics.resolution*24;
            }
            findEndSeconds();
        }
        // check whether download has completed
        if (!wm.metrics.playbackData[wm.metrics.nextData]) {
            //console.log("nextData: " + wm.metrics.nextData + " undefined");
            wm.metrics.waitForData = true;
            setTimeout(runLoop, 250);
            return;
        } else {
            wm.metrics.waitForData = false;
        }
        // loop until explicitly stopped
        wm.metrics.currentData = wm.metrics.nextData;
        wm.metrics.nextData = (wm.metrics.nextData + 1) % 2; 
        wm.metrics.playbackData[wm.metrics.nextData] = undefined;
        downloadFrameSet(false);
        wm.metrics.index = 0;
    }
    wm.metrics.metricsData =
        wm.metrics.playbackData[wm.metrics.currentData].timelineData[wm.metrics.index].metrics;
    var seconds =
        wm.metrics.playbackData[wm.metrics.currentData].timelineData[wm.metrics.index].timestamp;
    var timeDisplay = document.getElementById("animationTime");
    timeDisplay.innerHTML = "Time: <b>" + convertFromSeconds(seconds) + "</b>";
    updateLinks();
    wm.metrics.index++;
    if (!wm.metrics.paused) {
        setTimeout(runLoop, 1000);
    }
}

function initNextFrameSet(data) {
    console.log("initNextFrameSet called");
    hideLoadingPopup();
    if (checkError(data)) {
        console.log("returning because of checkError");
        return;
    }
    if (!wm.metrics.playbackOn) {
        console.log("returning because playback not on");
        return;
    }
    if (typeof(JSON) === 'object' &&
        typeof(JSON.parse) === 'function') {
        console.log("initNextFrameSet to JSON parse");
        if (!data) {
            console.log("no movie data");
        }
        wm.metrics.playbackData[wm.metrics.nextData] = JSON.parse(data); // native parsing available
        console.log("initNextFrameSet past JSON parse");
    } else {
        wm.metrics.playbackData[wm.metrics.nextData] = eval("(" + data + ")");
    }
    if (!wm.metrics.playbackData[wm.metrics.nextData].timelineData) {
        console.log("no timeline data");
        return;
    }
    // only happens first time
    console.log("currentData: " + wm.metrics.currentData);
    console.log("nextData: " + wm.metrics.nextData);
    if (wm.metrics.currentData == wm.metrics.nextData) {
        console.log("initial setup called");
        document.getElementById("playButton").style.backgroundColor = "#FFCC66";
        document.getElementById("stepButton").style.backgroundColor = "#FFFFFF";
        document.getElementById("pauseButton").style.backgroundColor = "#FFFFFF";
        document.getElementById("stopButton").style.backgroundColor = "#FFFFFF";
        wm.metrics.index = 0;
        wm.metrics.utilizationType =
            wm.metrics.playbackData[wm.metrics.nextData].timelineAttrs.utilizationType;
        wm.metrics.nextData = (wm.metrics.nextData + 1) % 2; 
        wm.metrics.currentSeconds += wm.metrics.resolution*24;
        findEndSeconds();
        downloadFrameSet(false);
        setTimeout(runLoop, 100);
    }
}

function downloadFrameSet(showWaitIndicator) {
    wm.metrics.playbackOn = true;
    var historyReqParams = "{'startSeconds':'" + wm.metrics.currentSeconds +
            "','endSeconds':'" + wm.metrics.currentEndSeconds + "','aggrSeconds':'" +
            wm.metrics.resolution + "'";
    if (wm.weathermap.metricTypeChoice === 0) {
        historyReqParams += ",'metricType':'average'";
    } else {
        historyReqParams += ",'metricType':'max'";
    }
    if (wm.weathermap.metricChoice == 1 ) {
        historyReqParams += ",'reservations':'hi'}";
    } else if (wm.weathermap.metricChoice == 2) {
        historyReqParams += ",'mbps':'hi'}";
    } else {
        historyReqParams += "}";
    }
    if (showWaitIndicator) {
        showLoadingPopup();
        toggleOptionsEnabled(false);
    }
    GDownloadUrl(servletUrl + "servlet?action=getPlayback&historyRequest="+historyReqParams, function(data) {
        initNextFrameSet(data);
    });
}

// happens with initial play request
function requestPlayback(startSeconds, endSeconds, resolution) {
    console.log("start: " + startSeconds + ", end: " + endSeconds +
                ", resolution: " + resolution);
    wm.metrics.startSeconds = startSeconds;
    wm.metrics.endSeconds = endSeconds;
    wm.metrics.currentSeconds = startSeconds;
    wm.metrics.resolution = resolution;
    findEndSeconds();
    // loop won't run if info window open
    if (!wm.weathermap.flash && !wm.renderer.map.getInfoWindow().isHidden()) {
        //wm.renderer.map.closeInfoWindow();
    }
    downloadFrameSet(true);
}

function stepLoop() {
    if (!wm.metrics.playbackOn) {
        return;
    }
    wm.metrics.paused = true;
    document.getElementById("playButton").style.backgroundColor = "#FFFFFF";
    document.getElementById("stepButton").style.backgroundColor = "#FFCC66";
    document.getElementById("pauseButton").style.backgroundColor = "#FFFFFF";
    document.getElementById("stopButton").style.backgroundColor = "#FFFFFF";
    setTimeout(runLoop, 1000);
}

function pauseLoop() {
    if (!wm.metrics.playbackOn) {
        return;
    }
    wm.metrics.paused = true;
    document.getElementById("playButton").style.backgroundColor = "#FFFFFF";
    document.getElementById("stepButton").style.backgroundColor = "#FFFFFF";
    document.getElementById("pauseButton").style.backgroundColor = "#FFCC66";
    document.getElementById("stopButton").style.backgroundColor = "#FFFFFF";
}

function stopLoop() {
    if (!wm.metrics.playbackOn) {
        return;
    }
    wm.metrics.playbackOn = false;
    wm.metrics.paused = false;
    wm.metrics.currentData = 0;
    wm.metrics.nextData = 0;
    wm.metrics.waitForData = false;
    wm.metrics.startSeconds = 0;
    wm.metrics.endSeconds = 0;
    wm.metrics.currentSeconds = 0;
    wm.metrics.currentEndSeconds = 0;
    toggleOptionsEnabled(true);
    document.getElementById("playButton").style.backgroundColor = "#FFFFFF";
    document.getElementById("stepButton").style.backgroundColor = "#FFFFFF";
    document.getElementById("pauseButton").style.backgroundColor = "#FFFFFF";
    document.getElementById("stopButton").style.backgroundColor = "#FFCC66";
    wm.metrics.index = 0;
    var timeDisplay = document.getElementById("animationTime");
    timeDisplay.innerHTML = "Stopped";
    setTimeout(getMetrics, wm.metrics.timeoutInterval);
}

function aggrSliderMouseUp(value) {
    wm.metrics.aggrSeconds = (value / 2) * 60;
    console.log("aggrSeconds: " + wm.metrics.aggrSeconds);
    getMetrics();
}
